#pragma once

#include <QtCore/QList>
#include <boostext/util/make_shared.hpp>

#include "exports.hpp"
#include "Placement.hpp"




namespace Engine
{
	namespace Ui
	{
		struct ENGINE_UI_API Resizing
		{
			enum Type
			{
				/// The widget will grow/shrink equal with all other widgets
				Standard,

				/// The widget will take as much space as possible
				Greedy,

				/// The widget always takes the minimal size
				Minimum,
			};
		};
		///////////////////////////////////////////////////////////////////////////////////////////////

		/**
		 * A Layout is an optional addition to every widget.
		 * When attached to a widget, children can be added to
		 * the layout (instead of the widget itself).
		 * All children, added this way will be managed by the layout
		 * and will be repositioned/resized when necessary.
		 * All widgets that are simply added to a widget itself will
		 * not be affected by this.
		 */
		class ENGINE_UI_API Layout
		{
		public:

			SHARED(Layout);
			typedef std::vector<boost::shared_ptr<Widget>>   Widgets;

		private:

			/// This is a pointer to this instance
			weak_ptr                  m_this;

			/// This is a pointer to the widget we're attached to
			boost::weak_ptr<Widget>   m_attached;

			/// We need to keep track of all widgets again
			/// but this time it is sorted from the top to the bottom
			Widgets                   m_widgets;

		protected:

			Layout(boost::weak_ptr<Widget> attached);
			virtual void post_create(ptr _this);

		public:

			virtual ~Layout();



			/**
			 * @returns a pointer to the widget this layout is attached to
			 * @throws boost::bad_weak_ptr in case the widget has already been destroyed
			 */
			boost::shared_ptr<Widget> attached() const;

			/**
			 * Adds the given widget to this layout.
			 * The widget is from now on being managed by the layout and also
			 * added to the attached widget widget of this layout (if not already).
			 */
			boost::shared_ptr<Widget> add(boost::shared_ptr<Widget> widget);

			/**
			 * Removes the given widget from this layout.
			 * The widget is no longer being managed by the layout and
			 * also removed from the attached widget.
			 */
			//void remove(boost::shared_ptr<Widget> widget);

			/**
			 * Calculate the minimum possible size.
			 */
			virtual intsize2 calculateMinimumSize() const = 0;



			/**
			 * Calling this function will reposition all children
			 * accordingly and will also update attached widget's
			 * size, when necessary.
			 */
			virtual void repositionChildren() = 0;

		protected:

			/**
			 * Get the list of widgets.
			 */
			const Widgets& widgets() const;

			/**
			 * Test if there is at least one widget with the specified resizing type.
			 */
			bool hasWidget(Resizing::Type resizing) const;

			/**
			 * Calculate how many widgets with the given resizing type there are.
			 */
			uint32 numWidgets(Resizing::Type resizing) const;

		private:

			/**
			 * In case the widget this layout is attached to is getting
			 * resized, all children must be repositioned and resized.
			 */
			void onAttachedResized();

			/**
			 * In case a children is getting resized, other children may need
			 * to be resized, repositioned as well as the attached widget.
			 */
			void onChildResized();

			/**
			 * In case a children is being moved, other children may need
			 * to be moved and/or resized.
			 */
			void onChildMoved();

		protected:

			bool   m_moving;
			bool   m_resizing;
		};
		///////////////////////////////////////////////////////////////////////////////////////////
	}
	///////////////////////////////////////////////////////////////////////////////////////////////
}
///////////////////////////////////////////////////////////////////////////////////////////////////
